
#include "parser.h"

Parser::Parser(Lexer &l, Symtab &s, OrderGenerator &g) : lexer(l), symtab(s),generator(g)  {

}

Parser::~Parser() {

}

void Parser::next() {
    token = lexer.fetch();
}

void Parser::process() {
    next(); //读取下一个标记
    program(); //解析程序文法
}

//文法：prog -> cdsmt prog|~
void Parser::program() {
    if (token->tag == END) {
        return;
    }
    cdsmt(); //解析代码段文法
    program(); //递归主程序
}

//cdsmt -> type define
void Parser::cdsmt() {
    Tag t = defType();
    define(t);
}

Tag Parser::defType() {
    Tag t = token->tag;
    if(t == INT || t == CHAR || t == VOID || t == STR || t == BOL){
        next();
    }
    return t;
}

//define-> defone deflist defStruct| fun
void Parser::define(Tag t) {
    if(t == STRUCT){
        defStruct(true);
        return;
    }
    Tag cur_tag = token->tag;
    if(cur_tag== MUL){
        next();
    }
    if(cur_tag == ID){
        string idName = ((Id *)token)->name;
        next();
        defOne(t, idName, false);
    } else{
        printf("\nID[%s] is not correct, error line is: %s\n", token->toString().c_str(), lexer.lineInfo().c_str());
        exit(1);
    }
}

//defone -> ID defvar func| assign;
//defvar -> idvar deflist|~
//deflist -> COMMA idvar|~
//idvar -> NUM STR CH | assign
void Parser::defOne(Tag t, string idName, bool ptr) {
    //先判断是否为函数，“(“开头为函数，否则为变量
    if (token->tag == LPR) {
        defFun(t, idName);
    } else{
        vector<string> ids = {idName};
        defVar(t, ids, ptr);
    }
}

//defvar -> idvar idlist|~
void Parser::defVar(Tag t, vector<string> &ids, bool ptr) {
    vector<Var*> val_seq;
    //根据”,“判断变量是单个还是多个
    if (token->tag == COMMA) {
        defList(t, ids, ptr);
    } else {
        Var *value = idVar();
        Var *var = symtab.getVar(ids.front());
        if (var) {
            var->setData(value);
        } else {
            var = new Var(ids.front(), value, t, symtab.getScope(), ptr);
            symtab.addVar(var);
            symtab.getCurFunc()->allocEsp(var);
        }
        if(ptr && t == MUL){//指针的赋值运算
            generator.genLeftCode(OP_SETV, var);
        }else{
            generator.genVarAssign(var);
            cout << "aaa:" << endl;
        }
    }
}

//idvar -> NUM STR CH | assign
Var *Parser::idVar() {
    return assign();
}

void Parser::defList(Tag t, vector<string> &ids, bool ptr) {
    while (true) {
        next();
        ids.push_back(((Id *) token)->name);
        next();
        if (token->tag != COMMA) { //判断下一个记号是否为","
            break;
        }
    }
    Var *v = idVar();
    for (string n: ids) {
        Var *var = symtab.getVar(n);
        if(!var){
            var = new Var(n, v, t, symtab.getScope(), false);
            symtab.addVar(var);
        }else{
            var->setData(v);
        }
    }
}

//fun -> ID LPA parms RPA funimpl
//funimpl -> statmt | SEM
void Parser::defFun(Tag t, string name) {
    next();
    vector<Var *> params;
    defParams(params);
    if (token->tag != RPR) {
        printf("\nfunc %s is not end with ')'", name.c_str());
        exit(1);
    }
    Func* func = new Func(t, name, params);
    func->incScope();
    symtab.addFunc(func);
    generator.genEntryCode(func);
    defFunImpl(func);  //函数实现
    generator.genExitCode(func);
    func->decScope();
}

void Parser::defFunImpl(Func *f) {
    next();
    Tag t = token->tag;
    if (t == LBE) {  //以"{"开始为函数实现
        next();
        defStatmt();
        next();
    } else if (t == SEM) {
        printf("\nfunc define is not suppor: %st error info is:\n", token->toString().c_str(), lexer.lineInfo().c_str());//函数定义
        exit(1);
    } else {
        printf("\nfunc end of error: %s, error info is:%s\n", token->toString().c_str(), lexer.lineInfo().c_str());
        exit(1);
    }
}

//statmt -> LBRA fragment RBRA
//fragment -> localval framgment | localstatmt fragment |RETURN expr SEM |~
//localval -> type defone deflist
void Parser::defStatmt() {
    defLocalval();
    defFramgment();
    if (token->tag == RBE) {
        return;
    }
    defStatmt();
}

void Parser::defFramgment() {
    Tag t = token->tag;
    if (t == RETURN) {
        next();
        Var* v = expr();
        generator.genRetCode(v, symtab.getCurFunc());
    } else{
        //暂不支持其他语句
    }
}

void Parser::defLocalval() {
    //局部变量可以无类型，但如果前文中未定义，则语法错误
    Tag t = defType();
    if(t == STRUCT){
        defStruct(false);
        next();
        return;
    }
    //若为指针类型
    bool is_ptr = false;
    if (token->tag == MUL) {
        is_ptr = true;
        next();
    }
    //若为变量或者函数调用
    string idName = ((Id *) token)->name;
    Func* func = nullptr;
    if (t == ID) {  //如果类型是ID，则查询其type
        Var * var = nullptr;
        //是否为变量
        var = symtab.getVar(idName);
        //是否为函数
        func = symtab.getFunc(idName);
        if(var == nullptr && func == nullptr){
            //是否是系统函数
            bool is_sys = false;
            Tag ft;
            for (auto item: sys_func){
                if (idName == item.first) {
                    is_sys = true;
                    ft = item.second;
                    break;
                }
            }
            if (is_sys) {
                func = new Func(ft, idName, true);
            } else{
                printf("\nthe id: %s not declared, error info is:%s", idName.c_str(), lexer.lineInfo().c_str());
                exit(1);
            }
        }
    }
    next();
    vector<string> ids = {idName};
    Tag tg = token->tag;
    if (tg == LPR) {//函数调用
        funcallexpr(idName, func);
        next();
    } else if(tg == POINT){//结构体的变量访问
        structcall(idName);
    } else{
        defVar(t, ids,is_ptr);
    }
}

void Parser::defParams(vector<Var *> &params) {
    if (token->tag == RPR) {//参数列表为空
        return;
    }
    Tag t = defType();
    string idName = ((Id *) token)->name;
    next();
    vector<int> &scope = symtab.getScope();
    Var* var = new Var(t, idName, scope);
    params.push_back(var);
    symtab.addVar(var);
    //若形参为多个则递归读取
    if(token->tag == COMMA){
        next();
        defParams(params);
    }

}

//assign-> ASSIGN expr | ~
Var *Parser::assign() {
    Tag tag = token->tag;
    if (tag == ASSIGN) {
        next();
        return expr();
    } else{
        printf("\nassign expression is not correct, error info is:[%s]\n", lexer.lineInfo().c_str());
        exit(1);
    }
}

//expr -> addexpr
Var *Parser::expr() {
    Var *var = addexpr();
    if (token->tag == SEM) {
        next();
    }
    return var;
}

//addexpr -> iterm addpart
//addpart -> addopr iterm addpart|~
//addopr -> ADD SUB
Var *Parser::addexpr() {
    Var *var = iterm();
    return addpart(var);
}

Var *Parser::iterm() {
    Var *var = factor();
    return itermpart(var);
}

Var *Parser::itermpart(Var *var) {
    Tag t = token->tag;
    if (t == MUL || t == DIV) {
        next();
        Var *s_var = factor();
        string tempName = generator.genTempNo(TMP_0, TMP_N);
        Var *tmp = new Var(var->getType(), tempName, symtab.getScope());
        Operation op = t == MUL ? OP_MUL : OP_DIV;
        generator.genOpCode(op, tmp, var, s_var);
        return itermpart(tmp);
    } else if(t == POINT){  //结构体成员变量访问
        next();
        string v_name = ((Id*)token)->name;  //被访问的变量名
        Var* r_var = var->getStructVar(v_name);
        if(!r_var){
            printf("\nthe struct var is illegal: %s, error info is: %s", v_name.c_str(), lexer.lineInfo().c_str());
            exit(-1);
        }
        string tempName = generator.genTempNo(TMP_0, TMP_N);
        Var *tmp = new Var(r_var->getType(), tempName, symtab.getScope());
        generator.genOpCode(OP_POINT, tmp, var, r_var);
        next();
        return tmp;
    }
    return var;
}

//factor -> leftopr factor |valpart
//leftopr -> ! & ++ --
//valpart -> val rightpor
//rightopr -> ++ --
//val -> ID |LPA expr RLA| NUM|CHAR|STRING|BOL
Var *Parser::factor() {
    Tag t = token->tag;
    //左结合语句暂支持&(取址),*(取值),此外还有--，++,!,-
    if (t == SUB || t == NOT || t == LEA || t == MUL) {
        next();
        Var *v = factor();
        printf("NE_TMP = -%s\n", v->getName().c_str());
        //左结合语句生成
        Var *tmp = nullptr;
        if(t == LEA){
            tmp = generator.genLeftCode(OP_LEA, v);
        } else if(t == MUL){
            tmp = generator.genLeftCode(OP_GETV, v);
        }
        return tmp;
    } else {
        return valpart();
    }

}

Var *Parser::valpart() {
    return val();
}

Var *Parser::addpart(Var *val) {
    Tag tag = token->tag;
    if (tag == ADD || tag == SUB) {
        next();
        Var *vars = iterm();
        string tempName = generator.genTempNo(TMP_0, TMP_N) ;
        Var *temp = new Var(INT, tempName, symtab.getScope());
        string mark = tag == ADD ? "+" : "-";
        //printf("code: [%s %s %s]\n", val->getName().c_str(), mark.c_str(), vars->getName().c_str());
        Operation op = tag == ADD ? OP_ADD : OP_SUB;
        generator.genOpCode(op, temp, val, vars);
        //next();
        return addpart(temp);
    }
    return val;
}

//val -> ID |LPR expr RLR| NUM|CHAR|STRING|BOL|STRUCT
Var *Parser::val() {
    Tag t = token->tag;
    if (t == ID) {
        string idName = ((Id *) token)->name;
        next();
        if (token->tag == LPR) {//函数调用
            return funcallexpr(idName, nullptr);
        } else {//否则为变量
            return symtab.getVar(idName);
        }
    } else if (t == NUM || t == BOL) {
        Var *var = new Var(token);
        symtab.addVar(var);
        next();
        return var;
    } else if(t == STR || t == CHAR){
        Var *var = new Var(token);
        var->setName(generator.genTempNo(TMP_0, var->getName()));
        //计算表变量的esp偏移
        symtab.getCurFunc()->allocEsp(var);
        generator.genVarAssign(var);
        symtab.addStrSeq(var);
        next();
        return var;
    } else {
        printf("\nnot support other val type: %s, error info is: %s", to_string(t).c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
}

Var* Parser::funcallexpr(string name, Func* func){
    vector<Var*> args;
    next();
    Tag tag = token->tag;
    if(tag != RPR) {
        while (true) { //循环读取实参，实参还可能是另一个表达式
            args.push_back(expr());
            Tag t = token->tag;
            if (t != COMMA || t == RPR) {
                break;
            } else{
                next();
            }
        }
    }
    if(!func){
        func = symtab.getFunc(name);
        if(!func){
            for (auto item: sys_func){
                if (name == item.first) {
                    func = new Func(item.second, name, true);
                    break;
                }
            }
        }
        if(!func){
            printf("\nfunc [%s] not exist",name.c_str());
            exit(1);
        }
    }
    Tag rtype = func->getType();
    string rename = generator.genTempNo(TMP_0, TMP_N);
    Var* res = rtype == VOID ? nullptr : new Var(rtype, rename, symtab.getScope());
    generator.genFuncCode(OP_CALL, func, args, res);
    next();
    return res;
}

Var *Parser::defStruct(bool global) {
    Var *var = new Var(token);
    if(global){
        symtab.addGlobalVar(var);
    }
    next();
    Tag t = token->tag;
    if(t == LBE){//结构体声明
        next();
        defStructVar(var);
    } else if(t == ID){//结构体变量，与普通变量一样
        var->setName(((Id *) token)->name);
        string type = var->getStructType();
        Var *s_def = symtab.getGlobalVar(type);
        if (!s_def) {//查询该结构体是否已经定义，否则报错
            printf("\nthe struct type is illegal: %s, error info is: %s", type.c_str(), lexer.lineInfo().c_str());
            exit(-1);
        }
        vector<Var*> t_var;
        vector<Var*> s_var = s_def->getStructVar();
        t_var.assign(s_var.begin(), s_var.end());
        var->setStructVar(t_var);
        symtab.addVar(var);//结构体变量无需分配offset
        next();
    } else{
        printf("\nnot support struct type: %s, error info is: %s", to_string(t).c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
    return nullptr;
}

void Parser::defStructVar(Var *var) {
    Tag t = defType();
    bool is_ptr = false;
    if (token->tag == MUL) {
        is_ptr = true;
        next();
    }
    Tag v_tag = token->tag;
    if(v_tag == ID || v_tag == STRUCT){
        string idName = ((Id *) token)->name;
        var->addStructVar(new Var(t, idName, is_ptr));
        next();
        while (true) {
            if(token->tag == COMMA){
                next();
                var->addStructVar(new Var(t, idName, is_ptr));
                next();
            } else{
                next();
                break;
            }
        }
    } else if(v_tag == RBE){
        return;
    } else{
        printf("\nthe struct define is illegal: %s, error info is: %s", to_string(t).c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
    defStructVar(var);
    next();
}

//per.age = 10;
void Parser::structcall(string name) {
    next();
    string v_name = ((Id*) token)->name;  //结构体中被访问的变量名称:per.age
    next();
    Var *value = idVar();  //变量的赋值
    Var *s_var = symtab.getVar(name);  //从变量表中获取结构体申明的变量
    if (!s_var) {
        printf("\nthe local var is illegal: %s, error info is: %s", s_var->getName().c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
    //根据结构体变量的type查询全局变量表中的结构体的定义，判断访问的成员变量是否合法
    Var * s_def = symtab.getGlobalVar(s_var->getStructType());  //获取结构体的定义
    if (!s_def) {
        printf("\nthe struct is illegal: %s, error info is: %s", s_var->getStructType().c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
    Var* v_def = s_def->getStructVar(v_name);//判断被访问的成员变量是否合法
    if (!v_def) {
        printf("\nthe struct var is illegal: %s, error info is: %s", v_name.c_str(), lexer.lineInfo().c_str());
        exit(-1);
    }
    //给结构体变量s_var中的具体成员变量v_name赋值
    Var *var = s_var->getStructVar(v_name);
    var->setData(value);
    symtab.addVar(var);  //添加局部变量
    symtab.getCurFunc()->allocEsp(var);  //分配栈内存
    generator.genVarAssign(var);  //生产赋值的中间代码
}


